# ArrowTexture - Displays text in rounded rectancle box
# Copyright (C) 2007 Lauri Taimila
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

__licence__ = "GPLv2"
__copyright__ = "2007, Lauri Taimila"
__author__ = "Lauri Taimila <lauri@taimila.com>"

import clutter
from clutter.cluttercairo import CairoTexture

class ArrowTexture(CairoTexture):
    """Clutter CairoTexture which represents an arrow."""
    
    # Arrow direction (One of these should be passed as a paramter)
    UP = 0
    DOWN = 1
    RIGHT = 2
    LEFT = 3
    
    def __init__(self, size, fg, bg, direction):
        """
        Initialize ArrowTexture
        @param size: Width and height of the texture
        @param fg: Foreground color (arrows)
        @param bg: Background color (background)
        @param direction: Arrow direction UP,DOWN,RIGHT or LEFT (class constant)
        """
        CairoTexture.__init__(self, size, size)
        context = self.cairo_create()
        context.scale(size, size)
        fg_cairo = self._clutterColorToCairoColor(fg)
        bg_cairo = self._clutterColorToCairoColor(bg)
        
        # Draw background
        context.set_line_width (0.15)
        context.set_source_rgba(bg_cairo[0], bg_cairo[1], bg_cairo[2], bg_cairo[3])
        self._roundedrec(context, 0, 0, 1, 1, 0.08, 0.1)
        context.fill()
        
        # Draw arrow
        context.set_source_rgba(fg_cairo[0], fg_cairo[1], fg_cairo[2], fg_cairo[3])
        if direction == ArrowTexture.DOWN:
            context.move_to(0.25, 0.33)
            context.line_to(0.50, 0.66)
            context.line_to(0.75, 0.33)
            context.stroke()
        elif direction == ArrowTexture.UP:
            context.move_to(0.25, 0.66)
            context.line_to(0.50, 0.33)
            context.line_to(0.75, 0.66)
            context.stroke()
        elif direction == ArrowTexture.RIGHT:
            context.move_to(0.33, 0.25)
            context.line_to(0.66, 0.50)
            context.line_to(0.33, 0.75)
            context.stroke()
        elif direction == ArrowTexture.LEFT:
            context.move_to(0.66, 0.25)
            context.line_to(0.33, 0.50)
            context.line_to(0.66, 0.75)
            context.stroke()
        
        del(context) # Updates texture
    
    def _clutterColorToCairoColor(self, color):
        """
        Transform from 0-255 to 0-1.
        @param color: clutter.Color
        """
        r = float(color.red) / 255.0
        g = float(color.green) / 255.0
        b = float(color.blue) / 255.0
        a = float(color.alpha) / 255.0
        return r,g,b,a
    
    def _roundedrec(self,cr,x,y,w,h,radius_x=5,radius_y=5):
        #from mono moonlight aka mono silverlight
        #test limits (without using multiplications)
        # http://graphics.stanford.edu/courses/cs248-98-fall/Final/q1.html
        ARC_TO_BEZIER = 0.55228475
        if radius_x > w - radius_x:
            radius_x = w / 2
        if radius_y > h - radius_y:
            radius_y = h / 2

        #approximate (quite close) the arc using a bezier curve
        c1 = ARC_TO_BEZIER * radius_x
        c2 = ARC_TO_BEZIER * radius_y

        cr.new_path();
        cr.move_to ( x + radius_x, y)
        cr.rel_line_to ( w - 2 * radius_x, 0.0)
        cr.rel_curve_to ( c1, 0.0, radius_x, c2, radius_x, radius_y)
        cr.rel_line_to ( 0, h - 2 * radius_y)
        cr.rel_curve_to ( 0.0, c2, c1 - radius_x, radius_y, -radius_x, radius_y)
        cr.rel_line_to ( -w + 2 * radius_x, 0)
        cr.rel_curve_to ( -c1, 0, -radius_x, -c2, -radius_x, -radius_y)
        cr.rel_line_to (0, -h + 2 * radius_y)
        cr.rel_curve_to (0.0, -c2, radius_x - c1, -radius_y, radius_x, -radius_y)
        cr.close_path ()
